package main

import "fmt"

/**
在golang中所有的参数类型都是值传递，只不过值类型（基础类型和结构体）传递的是值在内存中的拷贝，而值的指针类型传递的是值的内存地址的指针的拷贝，所以指针类型的接口看起来（也可以简单理解为）引用传递
*/
// 引用类型
/**
下面要介绍的是引用类型，包括 map 和 chan。

map
*/
func main() {
	// 在 Go 语言中，任何创建 map 的代码（不管是字面量还是 make 函数）最终调用的都是 runtime.makemap 函数。 最终返回的是*hmap，也就是hmap类型的指针类型，所以map的调用看起来像引用类型
	m := make(map[string]int)
	m["飞雪无情"] = 18
	fmt.Println("飞雪无情的年龄为", m["飞雪无情"])
	modifyMap(m)
	fmt.Println("飞雪无情的年龄为", m["飞雪无情"])
}
func modifyMap(p map[string]int) {
	p["飞雪无情"] = 20
}

/**
确实修改成功了。你是不是有不少疑惑？没有使用指针，只是用了 map 类型的参数，按照 Go 语言值传递的原则，modifyMap 函数中的 map 是一个副本，怎么会修改成功呢？
要想解答这个问题，就要从 make 这个 Go 语言内建的函数说起。在 Go 语言中，任何创建 map 的代码（不管是字面量还是 make 函数）最终调用的都是 runtime.makemap 函数。
小提示：用字面量或者 make 函数的方式创建 map，并转换成 makemap 函数的调用，这个转换是 Go 语言编译器自动帮我们做的。
从下面的代码可以看到，makemap 函数返回的是一个 *hmap 类型，也就是说返回的是一个指针，所以我们创建的 map 其实就是一个 *hmap。
*/

/**
同理 chan也是如此
func makechan(t *chantype, size int64) *hchan {
    //省略无关代码
}
*/

// 类型的零值
/**
在 Go 语言中，定义变量要么通过声明、要么通过 make 和 new 函数，不一样的是 make 和 new 函数属于显式声明并初始化。如果我们声明的变量没有显式声明初始化，那么该变量的默认值就是对应类型的零值。
从下面的表格可以看到，可以称为引用类型的零值都是 nil。
*/
